package com.javabi.common.collect.indexmap;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class TreeIndexMap<V> implements IIndexMap<V> {

	private final Map<Integer, V> indexToValueMap = Collections.synchronizedMap(new TreeMap<Integer, V>());

	@Override
	public int size() {
		return indexToValueMap.size();
	}

	@Override
	public boolean isEmpty() {
		return indexToValueMap.isEmpty();
	}

	@Override
	public void clear() {
		indexToValueMap.clear();
	}

	@Override
	public V get(int index) {
		if (index < 0) {
			throw new IllegalArgumentException("index=" + index);
		}
		return indexToValueMap.get(index);
	}

	@Override
	public V put(int index, V value) {
		if (index < 0) {
			throw new IllegalArgumentException("index=" + index);
		}
		return indexToValueMap.put(index, value);
	}

	@Override
	public void putAll(Map<Integer, V> map, boolean clear) {
		synchronized (indexToValueMap) {
			if (clear) {
				this.indexToValueMap.clear();
			}
			this.indexToValueMap.putAll(map);
		}
	}

	@Override
	public void putAll(Map<Integer, V> map) {
		this.indexToValueMap.putAll(map);
	}

	@Override
	public void putAll(IIndexMap<V> map) {
		putAll(map.toArray());
	}

	@Override
	public void putAll(V[] array) {
		synchronized (indexToValueMap) {
			for (int i = 0; i < array.length; i++) {
				if (array[i] != null) {
					put(i, array[i]);
				}
			}
		}
	}

	@Override
	public boolean putIfAbsent(int index, V value) {
		synchronized (indexToValueMap) {
			if (containsKey(index)) {
				return false;
			}
			put(index, value);
		}
		return true;
	}

	@Override
	public boolean containsKey(int index) {
		return get(index) != null;
	}

	@Override
	public void remove(int index) {
		indexToValueMap.remove(index);
	}

	@Override
	public List<V> values() {
		synchronized (indexToValueMap) {
			return new ArrayList<V>(indexToValueMap.values());
		}
	}

	public int getMaxIndex() {
		int maxIndex = 0;
		synchronized (indexToValueMap) {
			for (Integer index : indexToValueMap.keySet()) {
				if (maxIndex < index) {
					maxIndex = index;
				}
			}
		}
		return maxIndex;
	}

	@Override
	@SuppressWarnings("unchecked")
	public V[] toArray() {
		final Object[] array;
		synchronized (indexToValueMap) {
			array = new Object[getMaxIndex() + 1];
			for (Entry<Integer, V> entry : indexToValueMap.entrySet()) {
				int index = entry.getKey();
				V value = entry.getValue();
				array[index] = value;
			}
		}
		return (V[]) array;
	}

	@Override
	public String toString() {
		return indexToValueMap.toString();
	}

}
